package com.tianqi.code.lottery.domain.strategy.service.algorithm;

import com.tianqi.code.lottery.domain.strategy.model.vo.AwardRateVo;

import java.math.BigDecimal;
import java.security.SecureRandom;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 使用Hash的方式为奖品分配概率区间
 */
public abstract class AbstractHashDrawAlgorithm extends AbstractDrawAlgorithm {

    /**
     * 存放概率与奖品对应的散列结果，strategyId -> rateTuple
     */
    protected Map<Long, String[]> rateTupleMap = new ConcurrentHashMap<>();

    @Override
    protected void doInit(Long strategyId, List<AwardRateVo> awardRateVoInfoList) {

        String[] rateTuple = rateTupleMap.computeIfAbsent(strategyId, k -> new String[getRateTupleLength()]);

        int cursorVal = 0;
        for (AwardRateVo awardRateInfo : awardRateVoInfoList) {
            int rateVal = awardRateInfo.getAwardRate().multiply(new BigDecimal(100)).intValue();

            // 循环填充概率范围值
            for (int i = cursorVal; i < (rateVal + cursorVal); i++) {
                rateTuple[getIndex(i)] = awardRateInfo.getAwardId();
            }

            cursorVal += rateVal;

        }
    }

    @Override
    public String randomDraw(Long strategyId, List<String> excludeAwardIds) {

        // 获取策略对应的元祖
        String[] rateTuple = rateTupleMap.get(strategyId);
        assert rateTuple != null;

        // 随机索引
        int randomVal = new SecureRandom().nextInt(100);
        int idx = getIndex(randomVal);

        // 返回结果
        String awardId = rateTuple[idx];
        if (excludeAwardIds.contains(awardId)) return "未中奖";

        return awardId;
    }

    abstract protected int getRateTupleLength();

    abstract protected int getIndex(int i);
}
